<?php
// +----------------------------------------------------------------------------
// | Tke团队版权所属 [三十年河东三十年河西,莫欺少年穷.!]
// +----------------------------------------------------------------------------
// | Copyright (c) 2014 http://www.itdaodan.com All rights reserved.
// +----------------------------------------------------------------------------
// | Author: PHP@妖孽 <dino_ma@163.com>
// +----------------------------------------------------------------------------
namespace Admin\Model;
use Think\Model;
use Admin\Model\BaseModel;
/**
 * 用户组模型类
 */
class AuthGroupModel extends Model {
    const TYPE_ADMIN                = 1;                   // 管理员用户组类型标识
    const MEMBER                    = 'member';
    const AUTH_GROUP_ACCESS         = 'auth_group_access'; // 关系表表名
    const AUTH_EXTEND               = 'auth_extend';       // 动态权限扩展信息表
    const AUTH_GROUP                = 'auth_group';        // 用户组表名
    const AUTH_EXTEND_CATEGORY_TYPE = 1;              		// 分类权限标识

    protected $_validate = array(
        array('title','require', '必须设置用户组标题', Model::MUST_VALIDATE ,'regex',Model::MODEL_INSERT),
        array('description','0,80', '描述最多80字符', Model::VALUE_VALIDATE , 'length'  ,Model::MODEL_BOTH ),
    	array('title', '', '用户组名被占用', self::EXISTS_VALIDATE, 'unique'), //用户名被占用
    );
    
    /* 用户组模型自动完成 */
    protected $_auto = array(
    		array('status', 'getStatus', self::MODEL_BOTH, 'callback'),
    );
    
    /**
     * @todo 返回默认插入状态
     * @return number
     */
    protected function getStatus(){
    	return 1;
    }
	
    /**
     * @todo 更新/插入一条数据
     * @return boolean fasle 失败 ， 成功 返回完整的数据
     */
   public function update($data){
	   	/* 获取数据对象 */
	   	$data = empty($data) ? $_POST : $data;
	   	$data = $this->create($data);
	   	if(empty($data)){
	   		return false;
	   	}
	   	$data['module'] =  'admin';
	   	$data['type']   =  AuthGroupModel::TYPE_ADMIN;
	   	if(empty($data['id'])){ //新增数据
	   		$data['rules']='';
	   		$id = $this->add($data);
	   		$data['id'] = $id;
	   		if(!$id){
	   			\Think\Log::write('新增用户组:'.arr2str($data, ',').'失败');
	   			$this->error = '新增用户组出错！';
	   			return false;
	   		}
	   		\Think\Log::write('新增用户组:'.arr2str($data, ',').'成功');
	   	} else {//更新数据
	   	
	   		$status = $this->save($data); //更新基础内容
	   		if(false === $status){
	   			$this->error = '更新用户组出错！';
	   			\Think\Log::write('更新用户组:'.arr2str($data, ',').'失败');
	   			return false;
	   		}
	   		\Think\Log::write('更新用户组:'.arr2str($data, ',').'成功');
	   	}
	   	return $data;
   }
   
   /**
    * 返回用户所属用户组信息
    * @param  int    $uid 用户id
    * @return array  用户所属的用户组 array(
    *                                         array('uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'),
    *                                         ...)
    */
   static public function getUserGroup($uid){
	   	static $groups = array();
	   	if (isset($groups[$uid]))
	   		return $groups[$uid];
	   	$prefix = C('DB_PREFIX');
	   	$user_groups = M()
		   	->field('uid,group_id,title,description,rules')
		   	->table($prefix.self::AUTH_GROUP_ACCESS.' a')
		   	->join ($prefix.self::AUTH_GROUP." g on a.group_id=g.id")
		   	->where("a.uid={$uid} and g.status='1'")
		   	->select();
	   	$groups[$uid]=$user_groups?$user_groups:array();
	   	return $groups[$uid];
   }
   
   /**
    * @todo 返回用户组列表,默认返回正常状态的管理员用户组列表
    * @param array $where   查询条件,供where()方法使用
    */
   public function getGroups($where=array()){
		$map = array('status'=>1,'type'=>self::TYPE_ADMIN,'module'=>'admin');
		$map = array_merge($map,$where);
		return $this->where($map)->select();
   }
   
   /**
    * 把用户添加到用户组,支持批量添加用户到用户组
    * 示例: 把uid=1的用户添加到group_id为1,2的组 `AuthGroupModel->addToGroup(1,'1,2');`
    */
	public function addToGroup($uid,$group_id,$model=self::AUTH_GROUP_ACCESS){
		$uid = is_array($uid)?implode(',',$uid):trim($uid,',');
		$group_id = is_array($group_id)?$group_id:explode( ',',trim($group_id,',') );
		$obj_access = M($model);
		if( isset($_REQUEST['one_user']) ){
			//为单独某个用户添加用户组时,先删除已和他有关的用户组,避免循环查库出现高昂的i/o
			$del = $obj_access->where( array('uid'=>array('in',$uid)) )->delete();
		}
	   	$uid_arr = explode(',',$uid);
	   	$uid_arr = array_diff($uid_arr,array(C('USER_ADMINISTRATOR')));
	   	$user_list = M('AuthGroupAccess')->field('uid')->where(array('uid'=>array('in',$uid_arr)))->select();
	   	if(!empty($user_list)){
	   		$uid_arr = array_merge(array_diff($uid_arr, array_column($user_list, 'uid')));
	   		if(empty($uid_arr) || is_null($uid_arr)){
	   			return true;
	   		}
	   	}
	   	$data_list = array();
	   	if( $del!==false ){
	   		foreach ($uid_arr as $u){
	   			//判断用户id是否合法
	   			if(M('Member')->getFieldByUid($u,'uid') == false){
	   				$this->error = "编号为{$u}的用户不存在！";
	   				return false;
	   			}
	   			foreach ($group_id as $g){
	   				if( is_numeric($u) && is_numeric($g)   ){
	   					$data_list[] = array('group_id'=>$g,'uid'=>$u);
	   				}
	   			}
	   		}
	   		if(!empty($data_list)){
	   			$obj_access->addAll($data_list);
	   		}
	   	}
	   	if (!empty($data_list)) {
	   		if ($obj_access->getDbError()) {
	   			if( count($uid_arr)==1 && count($group_id)==1 ){
	   				//单个添加时定制错误提示
	   				$this->error = "不能重复添加";
	   			}else{
	   				$this->error = $obj_access->getDbError();
	   			}
	   			return false;
	   		}else{
	   			return true;
	   		}
	   	}else{
	   		return true;
	   	}
		
   }
   
   
   /**
    * 检查id是否全部存在
    * @param array|string $group_id  用户组id列表
    */
	public function checkId($modelname,$mid,$msg = '以下id不存在:'){
		if(is_array($mid)){
			$count = count($mid);
	   		$ids   = implode(',',$mid);
		}else{
			$mid   = explode(',',$mid);
			$count = count($mid);
			$ids   = $mid;
		}
		if(!is_object($modelname)){
			$modelname =M($modelname);
		}
		$list = $modelname->where(array($modelname->getPk()=>array('IN',$ids)))->getField($modelname->getPk(),true);
		if(count($list)===$count){
			return true;
		}else{
			$diff = implode(',',array_diff($mid,$list));
			$this->error = $msg.$diff;
			return false;
   		}
   }
   
   /**
    * 检查用户组是否全部存在
    * @param array|string $group_id  用户组id列表
    */
	public function checkGroupId($group_id){
		return $this->checkId('AuthGroup',$group_id, '以下用户组id不存在:');
	}
	
	/**
	 * 检查分类是否全部存在
	 * @param array|string $cid  栏目分类id列表
	 */
	public function checkCategoryId($cid){
		return $this->checkId('Category',$cid, '以下分类id不存在:');
	}
	
	/**
	 * @todo 将用户从用户组中移除
	 * @param int|string|array $group_id   用户组id
	 * @param int|string|array $cid   分类id
	 */
	public function removeFromGroup($uid,$group_id){
		return M(self::AUTH_GROUP_ACCESS)->where( array( 'uid'=>$uid,'group_id'=>$group_id) )->delete();
	}
	

	
	/**
	 * 返回用户拥有管理权限的扩展数据id列表
	 *
	 * @param int     $uid  用户id
	 * @param int     $type 扩展数据标识
	 * @param int     $session  结果缓存标识
	 * @return array
	 *
	 *  array(2,4,8,13)
	 *
	 */
	static public function getAuthExtend($uid,$type,$session){
		if ( !$type ) {
			return false;
		}
		if ( $session ) {
			$result = session($session);
		}
		if ( $uid == UID && !empty($result) ) {
			return $result;
		}
		$prefix = C('DB_PREFIX');
		$result = M()
		->table($prefix.self::AUTH_GROUP_ACCESS.' g')
		->join($prefix.self::AUTH_EXTEND.' c on g.group_id=c.group_id')
		->where("g.uid='$uid' and c.type='$type' and !isnull(extend_id)")
		->getfield('extend_id',true);
		if ( $uid == UID && $session ) {
			session($session,$result);
		}
		return $result;
	}
	
	/**
	 * 返回用户拥有管理权限的分类id列表
	 *
	 * @param int     $uid  用户id
	 * @return array
	 *
	 *  array(2,4,8,13)
	 *
	 */
	static public function getAuthCategories($uid){
		return self::getAuthExtend($uid,self::AUTH_EXTEND_CATEGORY_TYPE,'AUTH_CATEGORY');
	}
	
	
	
	/**
	 * 获取用户组授权的扩展信息数据
	 *
	 * @param int     $gid  用户组id
	 * @return array
	 *
	 *  array(2,4,8,13)
	 *
	 */
	static public function getExtendOfGroup($gid,$type){
		if ( !is_numeric($type) ) {
			return false;
		}
		return M(self::AUTH_EXTEND)->where( array('group_id'=>$gid,'type'=>$type) )->getfield('extend_id',true);
	}
	
	/**
	 * 获取用户组授权的分类id列表
	 *
	 * @param int     $gid  用户组id
	 * @return array
	 *
	 *  array(2,4,8,13)
	 *
	 */
	static public function getCategoryOfGroup($gid){
		return self::getExtendOfGroup($gid,self::AUTH_EXTEND_CATEGORY_TYPE);
	}
	
	
	/**
	 * 批量设置用户组可管理的扩展权限数据
	 *
	 * @param int|string|array $gid   用户组id
	 * @param int|string|array $cid   分类id
	 *
	 */
	static public function addToExtend($gid,$cid,$type){
		$gid = is_array($gid)?implode(',',$gid):trim($gid,',');
		$cid = is_array($cid)?$cid:explode( ',',trim($cid,',') );
	
		$Access = M(self::AUTH_EXTEND);
		$del = $Access->where( array('group_id'=>array('in',$gid),'type'=>$type) )->delete();
	
		$gid = explode(',',$gid);
		$add = array();
		if( $del!==false ){
			foreach ($gid as $g){
				foreach ($cid as $c){
					if( is_numeric($g) && is_numeric($c) ){
						$add[] = array('group_id'=>$g,'extend_id'=>$c,'type'=>$type);
					}
				}
			}
			$Access->addAll($add);
		}
		if ($Access->getDbError()) {
			return false;
		}else{
			return true;
		}
	}
	
	/**
	 * 批量设置用户组可管理的分类
	 *
	 * @param int|string|array $gid   用户组id
	 * @param int|string|array $cid   分类id
	 *
	 */
	static public function addToCategory($gid,$cid){
		return self::addToExtend($gid,$cid,self::AUTH_EXTEND_CATEGORY_TYPE);
	}
	
	
	
	/**
	 * 获取某个用户组的用户列表
	 *
	 * @param int $group_id   用户组id
	 *
	 */
	static public function memberInGroup($group_id){
		$prefix   = C('DB_PREFIX');
		$l_table  = $prefix.self::MEMBER;
		$r_table  = $prefix.self::AUTH_GROUP_ACCESS;
		$r_table2 = $prefix.self::UCENTER_MEMBER;
		$list     = M() ->field('m.uid,u.username,m.last_login_time,m.last_login_ip,m.status')
		->table($l_table.' m')
		->join($r_table.' a ON m.uid=a.uid')
		->join($r_table2.' u ON m.uid=u.id')
		->where(array('a.group_id'=>$group_id))
		->select();
		return $list;
	}
	
	
	/**
	 * 获取分类树，指定分类则返回指定分类极其子分类，不指定则返回所有分类树
	 * @param  integer $id    分类ID
	 * @param  boolean $field 查询字段
	 * @return array          分类树
	 */
	public function getTree($id = 0, $field = true){
		/* 获取当前分类信息 */
		if($id){
			$info = $this->departInfo($id);
			$id   = $info['id'];
		}
	
		/* 获取所有分类 */
		$map  = array('status' => array('gt', -1));
		$list = M('AuthDepartment')->field($field)->where($map)->order('sort')->select();
		int_to_string($list);
		$list = list_to_tree($list, $pk = 'id', $pid = 'father_id', $child = '_', $root = $id);
		/* 获取返回数据 */
		if(isset($info)){ //指定分类则返回当前分类极其子分类
			$info['_'] = $list;
		} else { //否则返回所有分类
			$info = $list;
		}
	
		return $info;
	}
	
	
	
	/**
	 * 获取部门详细信息
	 * @param  milit   $id 分类ID或标识
	 * @param  boolean $field 查询字段
	 * @return array     部门信息
	 */
	public function departInfo($id, $field = true){
		/* 获取分类信息 */
		$map = array();
		if(is_numeric($id)){ //通过ID查询
			$map['id'] = $id;
		} else { //通过标识查询
			$map['department_name'] = $id;
		}
		return M('AuthDepartment')->field($field)->where($map)->find();
	}
	
	
	/**
	 * @todo 将用户插入到部门中
	 * 示例: 把uid=1的用户添加到group_id为1,2的部门 `AuthGroupModel->addToDepartment(1,'1,2');`
	 */
	public function addToDepartment($uid,$department_id,$model='AuthDepartmentMember'){
	$uid = is_array($uid)?implode(',',$uid):trim($uid,',');
		$department_id = is_array($department_id)?$department_id:explode( ',',trim($department_id,',') );
		$obj_access = M($model);
		if( isset($_REQUEST['one_user']) ){
			//为单独某个用户添加用户组时,先删除已和他有关的用户组,避免循环查库出现高昂的i/o
			$del = $obj_access->where( array('uid'=>array('in',$uid)) )->delete();
		}
	   	$uid_arr = explode(',',$uid);
	   	$uid_arr = array_diff($uid_arr,array(C('USER_ADMINISTRATOR')));
	   	$user_list = M($model)->field('uid')->where(array('uid'=>array('in',$uid_arr)))->select();
	   	if(!empty($user_list)){
	   		$uid_arr = array_merge(array_diff($uid_arr, array_column($user_list, 'uid')));
	   		if(empty($uid_arr) || is_null($uid_arr)){
	   			return true;
	   		}
	   	}
	   	$data_list = array();
	   	if( $del!==false ){
	   		foreach ($uid_arr as $u){
	   			//判断用户id是否合法
	   			if(M('Member')->getFieldByUid($u,'uid') == false){
	   				$this->error = "编号为{$u}的用户不存在！";
	   				return false;
	   			}
	   			foreach ($department_id as $g){
	   				if( is_numeric($u) && is_numeric($g)   ){
	   					$data_list[] = array('department_id'=>$g,'uid'=>$u);
	   				}
	   			}
	   		}
	   		if(!empty($data_list)){
	   			$obj_access->addAll($data_list);
	   		}
	   	}
	   	if (!empty($data_list)) {
	   		if ($obj_access->getDbError()) {
	   			if( count($uid_arr)==1 && count($department_id)==1 ){
	   				//单个添加时定制错误提示
	   				$this->error = "不能重复添加";
	   			}else{
	   				$this->error = $obj_access->getDbError();
	   			}
	   			return false;
	   		}else{
	   			return true;
	   		}
	   	}else{
	   		return true;
	   	}
	}
	 
	
}

